package com.activiti.basic.exception;

import com.activiti.basic.model.ResponseUtil;
import com.activiti.basic.model.WebResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList;
import java.util.List;

/**
 * 全局异常拦截处理
 *
 * @author pisory
 * @version 1.0
 * @date 2020/4/5
 */
@RestControllerAdvice
@Slf4j
public class ExceptionControllerAdvice {

    /**
     * 业务处理异常统一处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public WebResponse<String> businessExceptionHandler(BusinessException ex) {
        log.error("业务异常", ex);
        return ResponseUtil.fail(ex.getMessage());
    }

    /**
     * 校验异常统一处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = ValidationException.class)
    public WebResponse<Boolean> validationExceptionHandler(ValidationException ex) {
        log.error("参数校验异常", ex);
        return ResponseUtil.fail(ex.status, false, ex.getMessage());
    }

    /**
     * 校验异常统一处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = ApprovalException.class)
    public WebResponse<Boolean> validationExceptionHandler(ApprovalException ex) {
        log.error("审批异常", ex);
        return ResponseUtil.fail(ex.status, false, ex.getMessage());
    }

    /**
     * 业务处理异常统一处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public WebResponse<String> paramError(HttpMessageNotReadableException ex) {
        log.error("参数格式不对异常", ex);
        return ResponseUtil.fail("参数格式不对，请确认再试");
    }

    @ExceptionHandler({TypeMismatchException.class})
    public WebResponse<String> requestTypeMismatch(TypeMismatchException ex) {
        log.error("参数类型不匹配异常", ex);
        return ResponseUtil.fail("参数类型不匹配,参数" + ex.getPropertyName() + "类型应该为" + ex.getRequiredType());
    }

    @ExceptionHandler({MissingServletRequestParameterException.class})
    public WebResponse<String> requestMissingServletRequest(MissingServletRequestParameterException ex) {
        log.error("缺少必要参数异常", ex);
        return ResponseUtil.fail("缺少必要参数,参数名称为" + ex.getParameterName());
    }

    /**
     * 全局异常捕捉处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public WebResponse<String> exceptionHandler(Exception ex) {
        log.error("系统异常", ex);
        return ResponseUtil.fail();
    }

    /**
     * 全局接口参数异常捕捉处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public WebResponse<List<ErrorInfo>> validException(MethodArgumentNotValidException ex) {
        log.error("参数错误", ex);
        List<ErrorInfo> errors = new ArrayList<ErrorInfo>();
        for (ObjectError oe : ex.getBindingResult().getAllErrors()) {
            if (oe instanceof FieldError) {
                FieldError fe = (FieldError) oe;
                errors.add(new ErrorInfo(fe.getField(), fe.getDefaultMessage()));
            } else {
                errors.add(new ErrorInfo(oe.getObjectName(), oe.getDefaultMessage()));
            }
        }
        return ResponseUtil.fail(errors, "参数错误");
    }

    @Data
    @AllArgsConstructor
    class ErrorInfo {

        private String error;

        private String errorMsg;
    }

}
